const gulp = require('gulp');
const sequence = require('gulp-sequence');
const shell = require('gulp-shell');

gulp.task('clean', () => {
	const del = require('del');
	return del('./dist/');
});

gulp.task('compile-ts', shell.task('node --max-old-space-size=4000 "./node_modules/typescript/bin/tsc"'));

gulp.task('watch-ts', shell.task('tsc -w -m umd'));

gulp.task('build-html', () => {
	const through = require('through2');
	const rename = require('gulp-rename');
	const path = require('path');
	const minifyHtml = require("gulp-minify-html");
	return gulp.src('./src/**/html.ts')
		.pipe(rename((file) => {
			const page_no = file.dirname;
			file.basename = page_no;
			file.extname = '.html';
			file.dirname = '../pages';
		}))
		.pipe(through.obj((chunk, enc, callback) => {
			const page_no = path.basename(chunk.path, '.html');
			const head = Buffer.from(`<!DOCTYPE html>
			<html>

			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
				<meta name="apple-mobile-web-app-capable" content="yes" />
				<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
				<meta name="renderer" content="webkit">
				<link rel="stylesheet" type="text/css" href="../css/iconfont.css">
				<link href="https://cdn.jsdelivr.net/npm/feidao-css/feidao.css" type="text/css" rel="stylesheet">
				<link rel="stylesheet" type="text/css" href="../css/daokes.css">
				<script src="../../node_modules/@dojo/loader/loader.js"></script>
				<script type="text/javascript">
					(() => {
						const baseUrl = '../../node_modules/';
						require.config({
							baseUrl: baseUrl,
							packages: [{
								name: 'daoke',
								location: '../dist'
							},{
								name: '@feidao/core',
								location: '@feidao/core/umd'
							},{
								name: '@feidao/web',
								location: '@feidao/web/umd'
							},{
								name: '@feidao/widgets',
								location: '@feidao/widgets/umd'
							},{
								name: '@feidao/animation',
								location: '@feidao/animation/umd',
								main: 'index'
							},{
								name: 'node-html-parser',
								location: 'node-html-parser/dist/umd',
								main: 'index'
							},{
								name: 'javascript-state-machine',
								location: './javascript-state-machine',
								main: 'state-machine'
							},{
								name: 'dask',
								location: 'dask/umd',
								main: 'index'
							},{
								name: 'mqtt',
								location: './mqtt/dist',
								main: 'mqtt'
							},{
								name: 'dot',
								location: 'dot',
								main: 'doT'
							},{
								name: 'nools-ts',
								location: 'nools-ts/umd'
							},{
								name: 'lodash-ts',
								location: 'lodash-ts/umd'
							},{
								name: 'he',
								location: './he',
								main: 'he.js'
							},{
								name: 'quill',
								location: '../node_modules/quill/dist',
								main: 'quill.min'
							},{
								name: 'i18next',
								location: './i18next/dist/umd',
								main: 'i18next'
							}]
						});
					})();
				</script>
			</head>
			<body>`, 'utf8');
			const tail = Buffer.from(`
				<script type="text/javascript">
				(() => {
					require(['daoke/${page_no}/nb'],function(main){
						const url = window.location.href;
						main.default(url).then((res) => {
							document.body.innerHTML = res;
							require(['daoke/${page_no}/b']);
						});
					});
				})();
			</script>
			</body></html>`, 'utf8');
			// const body = chunk.contents.toString('utf8');
			chunk.contents = Buffer.concat([head, /*Buffer.from(body.substring(body.indexOf('`') + 1, body.lastIndexOf('`'))), */tail]);
			// this.push(chunk);
			// callback();
			callback(null, chunk);
		}))
		.pipe(minifyHtml()) //压缩
		.pipe(gulp.dest('./dist/pages/'));
});

gulp.task('webpack', (cb) => {
	const dest = './dist/js/';
	const pack_file_path = `./dist/!(zj-)*/b.js`;
	const path = require('path');
	const webpack = require('webpack');
	const through = require('through');
	const ws = require('webpack-stream');
	gulp.src([pack_file_path])
		.pipe(((opts) => {
			return through(function (file) {
				file.named = path.basename(path.dirname(file.path));
				this.queue(file);
			});
		})())
		.pipe(ws({
			mode: 'production',
			// mode: 'development',
			optimization: {
				splitChunks: {
					name: 'feidao',
					chunks: 'all'
				}
			},
			externals: [
				// "nools" // this is a bad js file
			],
			output: {
				globalObject: 'window',
				publicPath: dest
			},
			module: {
				rules: [{
					test: /\.js$/,
					// exclude: /(node_modules|bower_components)/,
					exclude: /core-js|babel/,
					use: {
						loader: 'babel-loader'
					}
				}]
			}
		}, webpack))
		.pipe(gulp.dest(dest));
});

gulp.task('browser-sync', () => {
	const browserSync = require('browser-sync').create();
	browserSync.init({
		files: ['./dist/'],
		server: {
			baseDir: './dist/pages/',
			directory: true
		},
		online: false,
		serveStatic: ['./'],
		port: 8000
	});
});

gulp.task('daoke', ['watch-ts', 'build-html', 'browser-sync']);

gulp.task('nodejs', (cb) => {
	const dest = './dist/js';
	const pack_file_path = `./dist/!(zj-)*/n.js`;
	const path = require('path');
	const webpack = require('webpack');
	const through = require('through');
	const ws = require('webpack-stream');
	return (
		gulp.src([pack_file_path])
			.pipe(((opts) => {
				return through(function (file) {
					file.named = path.basename(path.dirname(file.path));
					this.queue(file);
				});
			})())
			.pipe(ws({
				mode: 'production',
				module: {
					rules: [{
						test: /\.js$/,
						// exclude: /(node_modules|bower_components)/,
						exclude: /core-js|babel/,
						use: {
							loader: 'babel-loader'
						}
					}]
				}
			}, webpack))
			.pipe(gulp.dest(dest))
	);
});

gulp.task('build-service', shell.task('tsc --outDir ./dist/js/service/ -p ./service/tsconfig.json'));

gulp.task('daoke-n', sequence('clean', 'compile-ts', 'nodejs', 'build-service'));

gulp.task('default', sequence('clean', 'compile-ts', 'webpack'));


gulp.task('config', async (cb) => {
	const fs = require('fs').promises;
	const files = await fs.readdir('./src');
	const fls = files.filter((f) => {
		if (f.indexOf('zj') > -1) {
			return f;
		}
	});
	fls.forEach((f) => {
		fs.writeFile('./src/' + f + '/config.ts', `export * from '../atom/config';\nexport const id = '${f}';`);
	});
});

gulp.task('nba2na', async (cb) => {
	const fs = require('fs').promises;
	const files = await fs.readdir('./src/')
	const fls = files.filter((f) => {
		if (f.indexOf('zj') > -1) {
			return f;
		}
	});
	fls.forEach(async (f) => {
		const files = await fs.readdir('./src/' + f + '/');
		const fns = files.filter((f) => {
			return /^nba/.test(f);
		});
		// nba**内容复制到na***
		const nas = await Promise.all(fns.map(async (n) => {
			const fn = n.replace('b', '');
			const data = await fs.readFile('./src/' + f + '/' + n, 'utf-8');
			const d = data.replace("import nodejs from '@feidao/web/atom/nodejs/msg-b/nodejs';", "import nodejs from '@feidao/web/atom/nodejs/msg/nodejs';").replace("import get_menus from '@feidao/web/atom/nodejs/authorization-b/get-menus';", "import get_menus from '@feidao/web/atom/nodejs/authorization/get-menus';");
			await fs.writeFile('./src/' + f + '/' + fn, d);
			return '\'' + fn.replace('.ts', '') + '\'';
		}));
		// 修改ns文件
		await fs.writeFile('./src/' + f + '/ns.ts', `export default {\n	'fd-events-init': [${nas.join(',')}]\n};\n`);

		// 修改n文件
		const ips = nas.map((n) => {
			return n.replace(/'/g, '');
		});;
		const ipn = ips.map((d) => {
			return `import ${d} from './${d}';`;
		});
		const nf = `import { HTMLElement } from 'node-html-parser';
import s from './ns';

import init from '@feidao/web/framework/nodejs/d/component';
import { id, spaceid, systemid, refsystemid } from './config';

${ipn.join('\n')}

export default function main(html: HTMLElement, url: string, query: any) {
const actions = { ${ips.join(',')} };

return init(id, s, actions, html, url, query, { spaceid, systemid, refsystemid });
}`;
		await fs.writeFile('./src/' + f + '/n.ts', nf);
	});
});

gulp.task('page-n', async (cb) => {
	const fs = require('fs').promises;
	const files = await fs.readdir('./src/');

	// 选择页面文件
	const fls = files.filter((f) => {
		return !/^zj|atom/.test(f);
	});
	fls.forEach(async (f) => {
		// const f = 'function';
		// 读取页面n文件
		const filepath_nb = `./src/${f}/nb.ts`;
		const data = await fs.readFile(filepath_nb, 'utf-8');
		// 如果没有内容，不处理
		if (!data) {
			console.error(`file [${filepath_nb}] is empty`);
			return;
		}
		let til = '';
		let bd = '<body>';
		let check = true;
		// 获取title
		const filepath_html = `./pages/${f}.html`;
		await fs.access(filepath_html)
			.then(async () => {
				const page_content = await fs.readFile(filepath_html, 'utf-8');
				if (page_content) {
					til = page_content.slice(page_content.indexOf('<title>') + 7, page_content.indexOf('</title>'));
					const bdf = page_content.slice(page_content.indexOf('<body'));
					bd = bdf.slice(0, bdf.indexOf('>') + 1);
				}
			})
			.catch((e) => {
				// 非菜单页面
				check = false;
				console.error(`There is no such file: [${f}]`);
			});
		// 写ns.ts和na001.ts
		fs.writeFile('./src/' + f + '/ns.ts', `export default {\n	'fd-events-server-check': ['na001'],\n	"fd-events-init": []\n}`);

		if (f != 'login') {
			// 非login页面
			const check_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';
import check_user from '../atom-n/online-check-user';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
	return await check_user(fd);
}`;
			const online_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';
import online_check from '../atom-n/online-check';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
	return await online_check(fd);
}`;

			fs.writeFile('./src/' + f + '/na001.ts', check ? check_page : online_page);
		} else {
			// login页面
			const login_page = `import { IFeidaoAiNodejsPage } from '@feidao/web/interfaces';

export default async function (fd: IFeidaoAiNodejsPage, ...args: any[]) {
}`;
			fs.writeFile('./src/' + f + '/na001.ts', login_page);
		}

		const actions = `import na001 from './na001';`;

		const imps = (data.match(/import\s+\w+\s+from\s+['|"]\.\.\/zj-\S+\/nb['|"];/g) || []).map((it, idx) => {
			const no = it.replace(/import\s+\w+\s+from\s+['|"](\.\.\/zj-\S+\/n)b['|"];/, '$1');
			return `import c${idx} from '${no}';`;
		});
		const imports = imps.join('\n');
		const params = ['html', 'url', 's', 'actions'].concat(imps.map((_, idx) => { return `c${idx}` })).join(', ');

		const constent = `import '@feidao/web/atom/nodejs/interfaces';
import html from './html';
import s from './ns';

import init from '@feidao/web/framework/nodejs/d/page';

////////////////////////////////////////////////////////////////////////////////
// import components
${imports}

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// import actions
${actions}

////////////////////////////////////////////////////////////////////////////////

feidao_exports.default = async (url: string) => {
	const actions = { na001 };

	const res = await init(${params});

	const html_str = \`<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="ie=edge">
		<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="renderer" content="webkit">
		<title>${til}</title>
		<link inline rel="stylesheet" type="text/css" href="./css/iconfont.css">
		<link inline href="https://cdn.jsdelivr.net/npm/feidao-css/feidao.css" type="text/css" rel="stylesheet">
		<link inline rel="stylesheet" type="text/css" href="./css/daokes.css">
		<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
		<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
		<script src="./js/feidao.js"></script>
		<script type="text/javascript">
			window.addEventListener('WebComponentsReady', function () {
				var t = document.createElement('script');
				t.src = './js/${f}.js';
				document.head.appendChild(t);
			});
		</script>
	</head>
	${bd}
	\${html.toString()}
	</body>
</html>
	\`;
	const html_obj = { data: html_str };
	if (typeof res === 'object' && Object.keys(res).length > 0) {
		const result = Object.assign({}, res, html_obj);
		return result;
	}
	return html_obj;
};`;
		fs.writeFile('./src/' + f + '/n.ts', constent);
	});
});